﻿using System;
using System.Net;
using System.Windows.Threading;
using TopMachine.Topping.Dto;
using Topping.Core.Logic;
using System.Collections.Generic;
using TopMachine.Topping.Common.Structures;
using Topping.Core.Logic.Client;
using TopMachine.Desktop.Overall;


namespace Topping.Core.Proxy.Local.Client
{
    public class MessageProxy : IMessageProxy, IDisposable
    {
        #region IMessageProxy Properties
        public GamePermissions GamePermissions { get; set; }
        public ISession Session { get; set; }
        private IGameState _GameState { get; set; }
        private IGameState _CurrentGameState { get; set; }
        #endregion

        private IProxy client
        {
            get
            {
                switch (ModeProxy)
                {
                    case 0:
                        return Topping.Core.Proxy.Local.Proxy.Instance;
                    case 1:
                        return Topping.Core.Proxy.Local.ServerProxy.Instance;
                }

                return null;
            }
        }

        public int ModeGlobal = 0;
        public int ModeProxy = 0;

        private static MessageProxy _messageProxy;
        public static MessageProxy Proxy
        {
            get
            {
                if (_messageProxy == null)
                {
                    _messageProxy = new MessageProxy();
                }

                return _messageProxy;
            }
        }
        public void DeleteCopy() 
        {
            if (_CurrentGameState != null)
            {
                _CurrentGameState.Dispose();
                _CurrentGameState = null;
            }
        }

        public IGameState GameState 
        {
            get
            {
                if (_CurrentGameState != null)
                {
                    return _CurrentGameState;
                }
                else 
                {
                    return _GameState;
                }
            }

            set 
            {
                _GameState = value;
            }
        } 

        Guid MemoryCheckId;

        public MessageProxy()
        {
            MemoryCheckId = MemoryCheck.Register(this, this.GetType().FullName);
        }

        public void Stop()
        {
            //StopTimer();
            //ThreadMessager.Instance.StopTimer();
        }

        public void Start()
        {
            GetRoomsDto();
            GetPlayers();
            LoadTimer();
        }

        public void InitializeOnline()
        {
            ModeProxy = 1;
            this.GamePermissions = Logic.Client.GamePermissions.CanChat | Logic.Client.GamePermissions.CanValidate;
            if (Session != null)
            {
                ((IDisposable)Session).Dispose(); 
            }
            Session = new Client.Session();

        }

        public void InitializeLocal()
        {
            ModeProxy = 0;
            this.GamePermissions = Logic.Client.GamePermissions.CanValidate | Logic.Client.GamePermissions.CanEndRound | Logic.Client.GamePermissions.CanPauseRound;

            if (Session != null)
            {
                ((IDisposable)Session).Dispose();
            }

            Session = new Client.Session();

        }

        public bool CheckVersion(string version)
        {
            return client.CheckVersion(version);
        }

        #region Timer to Get MESSAGES
        /* public void LoadTimer()
        {
            ThreadMessager.InitializeInstance(); 
        }*/


        public bool isLoading = false;
        public bool isSuspended = false;

        System.Windows.Forms.Timer tmr = null;

        public void StopTimer()
        {
            // tmr.Stop();
            tmr.Enabled = false;
            tmr.Dispose();
            tmr = null;
        }

        public void LoadTimer()
        {
            if (tmr != null)
            {
                tmr.Enabled = false;
                tmr.Dispose();
                tmr = null;
            }

            tmr = new System.Windows.Forms.Timer();
            tmr.Interval = 5000;
            tmr.Tick += new EventHandler(tmr_Tick);
            tmr.Start();
        }

        void tmr_Tick(object sender, EventArgs e)
        {
            client.GetMessages();
        }


        public void Suspend()
        {
            isSuspended = true;
            tmr.Enabled = false; ;
        }

        public void Resume()
        {
            isSuspended = false;
            tmr.Enabled = true;
        }


        public void QueueMessages(List<MessageDto> messages)
        {
            isLoading = true;
            foreach (MessageDto m in messages)
            {

                try
                {
                    Session.HandleMessage(m);
                }
                catch (Exception ee)
                {

                    NLog.LogManager.GetLogger("wcf").Error("QueueMessages : Message type is " + m.MessageType.ToString());

                    if (ee.InnerException != null)
                    {
                        NLog.LogManager.GetLogger("wcf").ErrorException("QueueMessages", ee.InnerException);
                    }
                    NLog.LogManager.GetLogger("wcf").ErrorException("QueueMessages", ee);
                    //throw;
                }
            }

            isLoading = false;

        }
        #endregion

        #region Users

        public List<UserDto> GetUsers()
        {
            List<UserDto> lst = client.GetUsers(); 
            return lst;
        }

        public bool UpdateUser(UserDto us)
        {
            bool ok = client.UpdateUser(us); 
            return ok;
        }

        public bool ChangedPwdUser(UserDto us,string NewPwd)
        {
            bool ok = client.ChangedPwdUser(us, NewPwd);
            return ok;
        }

        public bool DeleteUser(UserDto us)
        {
            bool ok = client.DeleteUser(us); 
            return ok;
        }
        public bool Login(string userName, string passWord)
        {
            bool ok = client.Login(userName, passWord, 6000) != Guid.Empty ? true : false;

            if (ok)
            {
                Session.Pseudo = userName;

            }

            return ok;
        }

        public void Logoff()
        {
            client.Logoff();
        }

        #endregion

        #region IMessage Proxy

        #region GameState
        public IGameState CreateGameState(ConfigGameDto dto)
        {
            LeaveAnyRoom();

            ResetRooms();
            Room room = new Room();
            room.Configuration = dto;

            RoomDto roomdt = MessageProxy.Proxy.InitRoom(room, true);

            Room cr = Session.Rooms.Find(p => p.RoomId == roomdt.RoomId);
            cr.SetDto(cr);

            Session.CurrentRoom = cr;
            cr.AddPlayer(Session.Pseudo);

            if (_GameState != null)
            {
                _GameState.Dispose();
                _GameState = null;
            }
            System.GC.Collect();


            _GameState = new GameState(cr);
            return GameState;
        }


        public IGameState LoadGameState()
        {
            DeleteCopy();

            if (_CurrentGameState != null) 
            {
                _CurrentGameState.Dispose();  
            }
            _CurrentGameState = new GameState(GameState.Room);
            if (_GameState != null)
            {
                _CurrentGameState.Copy(_GameState);
            }
            _GameState = new GameState(Session.CurrentRoom);
            return GameState;
        }

        public IGameState SetGameState(ConfigGameDto dto)
        {
            DeleteCopy();

            if (_GameState != null)
            {
                _GameState.Dispose();
                _GameState = null;
            }
            _GameState = new GameState(Session.CurrentRoom);
            return GameState;
        }

        public IGameState GetGameState()
        {
            return GameState;
        }

        #endregion

        #endregion

        #region IProxy Members
        public void SendMessage(MessageDto m)
        {
            if (ModeGlobal == 0)
            {
                client.SendMessage(m);
            }
        }


        public void ActivateChat()
        {
            if (GamePermissions.HasFlag(GamePermissions.CanChat))
            {
                client.ActivateChat();
            }
            else
            {
                client.DeactivateChat();
            }
        }

        public void DeactivateChat()
        {
            client.DeactivateChat();
        }

        public bool DeleteConfiguration(ConfigGameDto cfg)
        {
            return client.DeleteConfiguration(cfg);
        }

        public System.Collections.Generic.List<ConfigGameDto> GetConfigurations()
        {
            Session.Configurations = client.GetConfigurations();
            return Session.Configurations;
        }

        public List<RankingDto> GetRankings(string player, int year, int mont, Guid ConfigId)
        {
            return client.GetRankings(player, year, mont, ConfigId);
        }

        public GeneratedGameDto GetGame()
        {
            return client.GetGame();
        }

        public List<MessageDto> GetMessages()
        {
            return client.GetMessages();
        }
        public RoomDto GetRoom(int roomid)
        {
            return client.GetRoom(roomid);
        }

        private void GetPlayers()
        {
            string[] players = ListPlayers();
            Session.Pseudos = new List<string>();
            foreach (string p in players)
            {
                Session.Pseudos.Add(p);
            }
        }


        private void GetRoomsDto()
        {
            List<RoomDto> rooms = client.GetRoomsDto();
            Session.Rooms = new List<Room>();
            foreach (RoomDto r in rooms)
            {
                Session.Rooms.Add(new Room(r));
            }

        }

        public RoomDto InitRoom(Room room, bool generate)
        {
            RoomDto r = client.InitRoom(room, generate);
            Session.CurrentRoom = Session.Rooms.Find(p => p.RoomId == r.RoomId);
            Session.CurrentRoom.SetDto(r);
            return r;
        }

        public RoomDto JoinRoom(int roomId)
        {
            RoomDto rd = client.JoinRoom(roomId);
            Session.CurrentRoom = Session.Rooms.Find(p => p.RoomId == roomId);
            Session.CurrentRoom.SetDto(rd);
            string[] players = client.ListRoomPlayers(roomId);
            foreach (string s in players)
            {
                Session.CurrentRoom.AddPlayer(s);
            }

            return Session.CurrentRoom.GetDto();
        }

        public void GetListPlayedRound(string playerSearch)
        {
            client.GetListPlayedRound(playerSearch);
        }

        public void LeaveAnyRoom()
        {
            Session.CurrentRoom = null;
            client.LeaveAnyRoom();
        }

        public void LeaveRoom()
        {
            client.LeaveRoom();
            Session.CurrentRoom = null;
        }

        public string[] ListPlayers()
        {
            return client.ListPlayers();
        }

        public string[] ListRoomPlayers(int roomId)
        {
            string[] players = client.ListRoomPlayers(roomId);
            return players;
        }

        public string[] ListRoomActivePlayers(int roomId)
        {
            string[] players = client.ListRoomActivePlayers(roomId);
            return players;
        }

        public void SendMessageToRoom(int x, MessageDto m)
        {
            client.SendMessageToRoom(x, m);
        }

        public bool UpdateConfiguration(ConfigGameDto cfg)
        {
            return client.UpdateConfiguration(cfg);
        }

        public void SetGame(GeneratedGameDto game)
        {
            client.SetGame(game);
        }

        public void ResetRooms()
        {
            client.ResetRooms();
        }

        public void AddPlayedRound(PlayerSummaryDto summary, PlayedGameRoundDto pgr)
        {
            summary.Player = Session.Pseudo;
            pgr.Player = Session.Pseudo;
            GameState.GetPlayerSummary().Replace(summary, pgr);
            client.AddPlayedRound(summary, pgr);
        }

        public void StartGame()
        {
            client.StartGame();
        }

        public FinalRoomDto getFinalRoom(int roomid)
        {
            return client.GetFinalRoom(roomid);
        }

        public void FinishGame()
        {
            client.FinishGame();
        }

        public List<GamesDetailDto> GetGamesDetail(string player, int year, int mont, Guid configId)
        {
            return client.GetGamesDetail(player, year, mont, configId);
        }

        List<RankingDto> IMessageProxy.GetRankings(string player, int year, int mont, Guid ConfigId)
        {
            return client.GetRankings(player, year, mont, ConfigId);
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {

            if (Session != null)
            {
                ((IDisposable)Session).Dispose();
                Session = null;
            }

            DeleteCopy(); 
            if (_GameState != null)
            {
                _GameState.Dispose();
                _GameState = null;
            }

            if (tmr != null)
            {
                tmr.Enabled = false;
                tmr.Dispose();
                tmr = null;
            }
            ((IDisposable)client).Dispose();

            if (_messageProxy != null)
            {
                MemoryCheck.Unregister(MemoryCheckId);
                _messageProxy = null;
            }
        }

        #endregion



    }
}
